﻿#region Using's

using System;

#endregion

namespace MyUtils
{
	public struct NotNull<T> where T : class
	{
		readonly T _value;

		public NotNull(T value)
		{
			if (ReferenceEquals(null, value))
			{
				throw new ArgumentNullException(string.Empty, "Value can not be null");
			}
			_value = value;
		}

		public T Value
		{
			get { return _value; }
		}

		public static implicit operator T(NotNull<T> wrapper)
		{
			return wrapper.Value;
		}

		public static implicit operator NotNull<T>(T value)
		{
			return new NotNull<T>(value);
		}

		public override string ToString()
		{
			return _value.ToString();
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (obj is T)
			{
				return Equals(obj, _value);
			}
			if (obj is NotNull<T>)
			{
				return Equals(_value, ((NotNull<T>)obj).Value);
			}
			return false;
		}

		public bool Equals(NotNull<T> obj)
		{
			return Equals(obj._value, _value);
		}

		public override int GetHashCode()
		{
			return _value.GetHashCode();
		}

		public static bool operator ==(NotNull<T> wrapper, T value)
		{
			return Equals(value, wrapper._value);
		}
	
		public static bool operator ==(NotNull<T> wrapper, NotNull<T> wrapper2)
		{
			return Equals(wrapper2._value, wrapper._value);
		}

		public static bool operator !=(NotNull<T> wrapper, NotNull<T> wrapper2)
		{
			return !(wrapper == wrapper2);
		}

		public static bool operator !=(NotNull<T> wrapper, T value)
		{
			return !(wrapper == value);
		}

		public static bool operator !=(T value, NotNull<T> wrapper)
		{
			return !(wrapper == value);
		}

		public static bool operator ==(T value, NotNull<T> wrapper)
		{
			return Equals(value, wrapper._value);
		}
	}
}